package interaction.sampling;

import java.util.ArrayList;
import java.util.Collection;

import ddf.minim.analysis.FFT;

public class Sample extends ArrayList<Float> {
	private NumericAnalyzer analyzer;
	private Sample deltas;
	private static final Float ZERO = new Float(0);
	
	public Sample(Collection<? extends Float> c) {
		super(c);
	}

	public Sample(int initialCapacity) {
		super(initialCapacity);
	}

	public static Sample fromFftAverages(FFT data)
	{
		Sample result = new Sample(data.avgSize());
		for (int i = 0; i < data.avgSize(); i++) {
			result.add(data.getAvg(i));
		}
		return result;
	}

	public static Sample fromFft(FFT data)
	{
		Sample result = new Sample(data.specSize());
		for (int i = 0; i < data.specSize(); i++) {
			result.add(data.getBand(i));
		}
		return result;
	}
	
	public NumericAnalyzer getAnalyzer() {
		if (null == analyzer) {
			analyzer = new NumericAnalyzer(this);
		}
		return analyzer;
	}
	
	public Sample getDeltas()
	{
		if (null == deltas) {
			deltas = Samples.getLeftDeltaValues(this);
		}
		return deltas;
	}
	
	public double getAverage()
	{
		return getAnalyzer().getAverage();
	}
	
	public double getSum()
	{
		return getAnalyzer().getSum();
	}

	public Sample getDeviation(Sample from)
	{
		return getAnalyzer().getDeviation(from);
	}
	
	public Sample normalizeToAverage()
	{
		double average = getAverage();

		for (int i = 0; i < size(); i++) {
			set(i, (float) (get(i) / average));
		}
		
		return this;
	}
	
	public Sample compressRange(double min)
	{
		Sample result = new Sample(size());
		for (Float f : this) {
			if (Math.abs(f) > min) {
				result.add(f);
			}
		}
		return result;
	}
	
	public Sample getLevelLengths(double treshold)
	{
		Sample result = new Sample(size());
		float currentLevelLength = 0;
		float currentLevel = get(0);
		for (int i = 1; i < size(); i++) {
			float level = get(i);
			currentLevelLength++;
			
			if (Math.abs(currentLevel - level) > treshold) {
				result.add(currentLevelLength);
				currentLevelLength = 0;
				currentLevel = level;
			}
		}
		return result;
	}
	
	public Float get(int index)
	{
		if (index >= size()) {
			return ZERO;
		}
		return super.get(index);
	}
}
